package public

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"log"
	"strconv"
	"time"
	"woo-server/coms/structs"
	"woo-server/coms/utils"
	"woo-server/models/api"
	"woo-server/models/db/system"
)

// 结构
type LoginService struct {
	*structs.Common
}

// 初始化
func NewLoginService(com *structs.Common) *LoginService {
	return &LoginService{com}
}

func (l *LoginService) Login(context *gin.Context, username string, password string, codeKey string, code string) *api.ResultEntity {

	if username == "" || password == "" {
		return api.Error("账号或密码不能为空!")
	}
	verifyResult := base64Captcha.VerifyCaptcha(codeKey, code)
	if !verifyResult {
		return api.Error("验证码错误!")
	}

	userModel := system.NewUsers(l.Common)
	result, err := userModel.CheckLogin(username, password)
	if err != nil {
		return api.Error(err.Error())
	}
	if result.AdminUserId == 0 {
		utils.SetLoginCookie(context.Writer, context.Request, 0, "", 0)
		return api.Error("账号或密码错误")
	}
	fmt.Println("用户< " + result.NickName + " >登录了系统")
	//更新登录数据
	userModel.AutoSave("admin_user_id = ?", result.AdminUserId, map[string]interface{}{
		"last_login_time":   result.BeforeLoginTime,
		"before_login_time": time.Now(),
		"last_login_ip":     result.BeforeLoginIp,
		"before_login_ip":   utils.ClientIp(context.Request)})

	// 设置登录状态到cookie
	utils.SetLoginCookie(context.Writer, context.Request, result.AdminUserId, result.NickName, int(result.AdminRoleId))

	// 拼接Redis键值名
	RDSKey := "RoleMenuList_" + strconv.FormatInt(int64(result.AdminRoleId), 10)
	// 获取Redis缓存数据
	RDSResult, _ := utils.RedisClient.Get(RDSKey).Result()
	// 没缓存则实时取
	if RDSResult == "" {
		// 实例化菜单模型
		menuModel := system.NewMenus(l.Common)
		treeList, list := []structs.AdminMenus{}, []system.AdminMenus{}

		// roleId = 1 是超级管理员 拥有所有权限菜单
		if result.AdminRoleId == 1 {
			treeList, list = menuModel.GetAllMenu(false)
		} else {
			// 获取角色菜单id合集
			roleModel := system.NewRole(l.Common)
			role := roleModel.GetFirst("admin_role_id = ?", result.AdminRoleId)
			//我也不知道为什么直接给数据库 类型设置为[]uint8 会不行 查询的时候会数字全变了. 必须要字符串出来再转int数组才行
			var adminMenuId []int
			err := json.Unmarshal([]byte("["+role.AdminMenuId+"]"), &adminMenuId)
			if err != nil {
				log.Fatal(err)
			}

			treeList, list = menuModel.GetRoleMenu("admin_menu_id in ?", adminMenuId, false)
		}
		// 保存非树状权限菜单
		utils.RedisClient.Set(RDSKey+"_noTree", utils.ToJson(list), 0)
		// 保存树状权限菜单
		utils.RedisClient.Set(RDSKey, utils.ToJson(treeList), 0)
		return api.SuccessToJson(treeList, "登录成功1!")
	}
	// 将字符串Redis缓存改为AdminMenus结构体
	var RoleMenu []system.AdminMenus
	json.Unmarshal([]byte(RDSResult), &RoleMenu)
	return api.SuccessToJson(RoleMenu, "登录成功2!")

}

func (l *LoginService) Logout(context *gin.Context) *api.ResultEntity {
	utils.SetLoginCookie(context.Writer, context.Request, 0, "", 0)
	return api.Success("退出成功!")
}
